package org.example.learn.bytebuddy.make;

import net.bytebuddy.ByteBuddy;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.implementation.FixedValue;
import net.bytebuddy.implementation.MethodDelegation;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;

public class GenerateClass {

    private static void output(byte[] bytes,String className){
        FileOutputStream out = null;
        String path = GenerateClass.class.getResource("/").getPath() + className + ".class";
        try {
            out = new FileOutputStream(new File(path));
            out.write(bytes);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (null != out) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {

        // 创建类
        DynamicType.Unloaded<?> dynamicType = new ByteBuddy()
                .subclass(Object.class)
                // 设置要创建的类名称
                .name("org.example.learn.bytebuddy.Test")
                .make();
        // 输出生成的字节
        output(dynamicType.getBytes(),"Test");

        // 创建main方法
        DynamicType.Unloaded<?> dynamicType1 = new ByteBuddy()
                .subclass(Object.class)
                .name("org.example.learn.bytebuddy.Test1")
                // 创建的方法
                .defineMethod("main",void.class, Modifier.PUBLIC + Modifier.STATIC)
                // 方法参数
                .withParameter(String[].class,"args")
                // 拦截 并向方法内添加 局部变量和变量值 （创建局部变量）
                .intercept(FixedValue.value("Test Test"))
                .make();
        output(dynamicType1.getBytes(),"Test1");


        // 委托函数使用
        DynamicType.Unloaded<?> dynamicType2 = new ByteBuddy()
                .subclass(Object.class)
                .name("org.example.learn.bytebuddy.Test2")
                .defineMethod("main",void.class,Modifier.PUBLIC + Modifier.STATIC)
                .withParameter(String[].class,"args")
                // 拦截器内使用 MethodDelegation.to() 将信息委托给A.class
                // 拦截并委托
                .intercept(MethodDelegation.to(A.class))
                .make();
        output(dynamicType2.getBytes(),"Test2");

        // 执行创建的方法
        // 加载方法
        Class<?> clazz = dynamicType2.load(GenerateClass.class.getClassLoader()).getLoaded();
        clazz.getMethod("main",String[].class).invoke(clazz.newInstance(),(Object) new String[]{"张三"});
    }

}
